#include "login.h"
#include "ui_login.h"
#include "serverwindow.h"
#include <QDesktopWidget>
#include <QMessageBox>
#include "clientwindow.h"
#include "jsonparse.h"
#include "dboperation.h"
#include "taskqueue.h"
#include "clientthread.h"

Login::Login(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Login)
{
    ui->setupUi(this);

    // 设置默认角色
    ui->radioClient->setChecked(true);
    ui->savePasswd->setChecked(true);
    // 初始化当前窗口
    ui->stackedWidget->setCurrentIndex(0);  // 栈窗口模式显示登录
    initWindow(LoginWindow);

    connect(ui->setPage, &ConfigSet::goback, this, [=]()
    {
        // 栈窗口切换, 从设置 -> 登录
        ui->stackedWidget->setCurrentIndex(0);
        initWindow(LoginWindow);
        // ui->stackedWidget->setCurrentWidget(ui->loginPage);
    });

    // 加载登录信息
    // 按钮组
    m_btnGrp.addButton(ui->radioClient, 1);
    m_btnGrp.addButton(ui->radioServer, 2);
    void (QButtonGroup::*clicked)(int) = &QButtonGroup::buttonClicked;
    connect(&m_btnGrp, clicked, this, &Login::initLoginInfo);
    // 填充配置文件中的ID和密码
    initLoginInfo(1);
}

Login::~Login()
{
    delete ui;
}

void Login::initWindow(Login::Window type)
{
    // 窗口大小, 窗口的标题
    // QList<QString>
    QStringList nameList;
    nameList << "用户登录" << "客户端设置" << "服务器设置";

    // QSize: 宽, 高
    QSize size[]=
    {
        QSize(280, 240),
        QSize(300, 350),
        QSize(400, 480)
    };

    // 根据参数选择对应的属性设置给当前窗口
    setWindowTitle(nameList[type]);
    setFixedSize(size[type]);
}

void Login::initClient()
{
    // 创建子线程对象, 并且启动子线程
    ClientThread* subThread = new ClientThread;
    subThread->start();
    // 当当前创建被析构, 终止显线程, 释放对象
    // qApp是一个全局指针, 执向项目中唯一的应用程序对象
    connect(qApp, &QApplication::destroyed, this, [=]()
    {
        subThread->quit();  // 终止线程内部循环
        subThread->wait();  // 等待线程终止
        subThread->deleteLater();   // delete subThread;
    });

    // 主要的处理动作, 添加任务(添加到任务队列中)
    m_cliop = new ClientOperation;
    connect(this, &Login::sendLoginInfo, m_cliop, &ClientOperation::saveLoginInfo);
    connect(m_cliop, &ClientOperation::loginSuccess, this, [=]()
    {
        // 显示主界面, 登录成功
        ClientWindow* cliwin = new ClientWindow;
        cliwin->show();
        bool savePwd = ui->savePasswd->isChecked();
        // 加载登录信息
        if(savePwd)
        {
            // 获取用户输入数据
            QString userName = ui->netID->text();
            QString passwd = ui->netPasswd->text();
            bool cliRole = ui->radioClient->isChecked();
            JsonParse::Type type = cliRole ? JsonParse::Client : JsonParse::Server;
            JsonParse::getInstance()->writeLoginInfo(userName, passwd, type);
        }

        // 登录窗口隐藏
        accept();
    });
    connect(m_cliop, &ClientOperation::loginFail, this, [=]()
    {
         QMessageBox::warning(this, "登录", "您输入的Id或密码错误");
    });
}

void Login::initLoginInfo(int index)
{
    JsonParse::Type t = index == 1 ? JsonParse::Client : JsonParse::Server;
    LoginInfo info = JsonParse::getInstance()->readLoginInfo(t);
    ui->netID->setText(info.id);
    ui->netPasswd->setText(info.pwd);
}

void Login::resizeEvent(QResizeEvent *)
{
    // 1. 获取屏幕的尺寸
    // 通过应用程序对象得到 QDesktopWidget 类对象
    // [static] QDesktopWidget *QApplication::desktop()
    QDesktopWidget* desk = QApplication::desktop();
    // 2. 得到窗口的尺寸 width()/heigth()
    // 3. 计算新的坐标点, 将窗口进行移动 -> move()
    //     这个坐标点就是窗口左上角坐标
    int x = (desk->width() - this->width()) / 2;
    int y = (desk->height() - this->height()) / 2;
    this->move(x, y);
}

// 槽函数, 通过转到槽的方式添加的, connect操作就不需要写了
void Login::on_setBtn_clicked()
{
    // 切换到设置窗口
    ui->stackedWidget->setCurrentWidget(ui->setPage);

    // 根据角色进行设置窗口的跳转
    // 判断是不是客户端角色
    bool bl = ui->radioClient->isChecked();
    if(bl)
    {
        // 跳转到客户端设置窗口
        ui->setPage->showPage(ConfigSet::Client);
        initWindow(ClientConfig);
    }
    else
    {
        // 跳转到服务器设置
        ui->setPage->showPage(ConfigSet::Server);
        initWindow(ServerConfig);
    }
}

// 登录
void Login::on_loginBtn_clicked()
{
    // 取出登录窗口中输入的信息
    QString id = ui->netID->text();
    QString passwd = ui->netPasswd->text();

    // 判断是不是客户端角色
    bool bl = ui->radioClient->isChecked();
    // 检测客户端/服务器对应的配置文件是否存在, 不存在就跳转到设置窗口
    JsonParse::Type t = bl ? JsonParse::Type::Client : JsonParse::Type::Server;
    bool flag = JsonParse::getInstance()->configIsExist(t);
    if(!flag)
    {
        // 配置文件不存在, 让窗口自动切换到设置界面
        on_setBtn_clicked();
        return;
    }

    ////////////////////// 登录 ////////////////////
    // 登录要进行服务器连接:
    //  - 1. 服务器端可以直接连接数据库
    //  - 2. 客户端不能直接连接数据库(没有资格), 需要先连接服务器, 通个服务器完成数据库操作
    if(bl)
    {
        if(m_cliop == NULL)
        {
            initClient();
        }
        emit sendLoginInfo(id, passwd);

        // 添加登录的任务到任务队列中
        TaskQueue* taskQ = TaskQueue::getInstance();
        // 添加秘钥协商的任务
        ArgInfo* arg1 = new ArgInfo;
        arg1->prepare = ClientOperation::consultPrepare;
        arg1->dispose = ClientOperation::consultDispose;
        arg1->object  = m_cliop;
        taskQ->addTask(ClientOperation::communication, arg1);

        // 添加一个登录的任务
        ArgInfo* arg2 = new ArgInfo;
        arg2->prepare = ClientOperation::loginPrepare;
        arg2->dispose = ClientOperation::loginDispose;
        arg2->object  = m_cliop;
        taskQ->addTask(ClientOperation::communication, arg2);
    }
    else
    {
        // 创建一个可以操作数据库的对象
        DBOperation db;
        SerConfig conf = JsonParse::getInstance()->readServerConfig();
        db.connectDB(conf.dbUserName, conf.dbPasswd, conf.dbHost);
        // 查询数据库
        flag = db.userAuthentication(id, passwd);
        if(!flag)
        {
            QMessageBox::warning(this, "登录", "您输入的Id或密码错误");
            return;
        }
        else
        {
            // 登录到服务器窗口
            ServerWindow* serWin = new ServerWindow;
            serWin->show();
            bool savePwd = ui->savePasswd->isChecked();
            if(savePwd)
            {
                JsonParse::getInstance()->writeLoginInfo(id, passwd, t);
            }

            // 隐藏或者关闭登录对话框
            accept();
        }
    }
}
